package com.fzk.controller;

import com.fzk.core.FileMeta;
import com.fzk.core.FileMetaStore;
import com.fzk.core.FileStoreService;
import com.fzk.router.ApiHandler;
import com.fzk.router.AutoRegister;
import com.fzk.router.MyAutowire;
import com.fzk.router.MyRequestMapping;
import com.fzk.server.HttpResponseUtil;
import com.fzk.server.StaticResourcesHandler;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpUtil;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
 * 资源下载
 *
 * @author uestcfzk
 * @datetime 2023-04-14 01:19:10
 */
@SuppressWarnings("unused")
@AutoRegister
public class DownloadController {
    public static final String downloadApiUri = "/fs/api/download";
    @MyAutowire(key = "fileService")
    private FileStoreService fileService;

    @MyRequestMapping(path = downloadApiUri, method = {"GET", "POST"})
    private final ApiHandler download = (ctx, request, params) -> {
        // 1.获取并检查key
        List<String> keys = params.get("key");
        if (keys.size() != 1) {
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.BAD_REQUEST, "参数key只能传1个");
            return;
        }
        String key = keys.get(0);
        if (key == null || key.isEmpty()) {
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.BAD_REQUEST, "参数key为空");
            return;
        }
        ctx.info("下载文件: key: " + key);

        // 2.获取文件元信息
        FileMetaStore.FileMetaWrapper wrapper = fileService.getFileMeta(key);
        if (wrapper == null) {
            ctx.warning(String.format("文件存储元信息不存在，可能已经删除, key: %s", key));
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.NOT_FOUND);
            return;
        }
        // 3.判断文件能否访问
        if (wrapper.meta.getUploadStatus() == FileMeta.Uploading) {
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.BAD_REQUEST, "文件还在上传过程中，请稍微访问");
            return;
        }
        if (wrapper.meta.getUploadStatus() == FileMeta.UploadFailed) {
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.BAD_REQUEST, "此文件key: %s, 已经上传失败, 无法访问");
            return;
        }
        // 4.获取文件存储路径，并判断是否存在
        Path path = Path.of(fileService.dataDir, wrapper.meta.getRelativePath());
        if (Files.notExists(path)) {
            String str = String.format("根据元信息保存的路径未找到文件，文件删除了? meta: %s", wrapper.meta);
            ctx.warning(str);
            HttpResponseUtil.sendError(ctx.getChannelCtx(), HttpUtil.isKeepAlive(request), HttpResponseStatus.NOT_FOUND, str);
            return;
        }
        // 3.传输文件
        StaticResourcesHandler.serve(ctx, request, path);
    };

    // 直接以目录uri进行访问
    @MyRequestMapping(path = {"/fs/statics*", "/fs/data*"})
    private final ApiHandler staticsResource = (ctx, request, params) -> {
        // 要先移除uri的第一个"/"
        Path path = Path.of(request.uri().replaceFirst("/fs/", ""));
        if (request.uri().endsWith("/")) {
            path = Path.of("statics/html/listFile.html");
        }
        StaticResourcesHandler.serve(ctx, request, path);
    };
}
